package com.eian.boot.common.aspect;

import com.eian.boot.common.annotation.DataScope;
import com.eian.boot.common.context.DataScopeContext;
import com.eian.boot.module.system.role.service.DataScopeService;
import com.eian.boot.security.utils.SessionHelper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * 数据权限AOP切面
 * 拦截@DataScope注解的方法，设置数据权限上下文
 *
 * @author alex.meng
 */
@Slf4j
@Aspect
@Component
@AllArgsConstructor
public class DataScopeAspect {

    private final DataScopeService dataScopeService;

    /**
     * 定义切点：拦截所有标注@DataScope注解的方法
     */
    @Pointcut("@annotation(com.eian.boot.common.annotation.DataScope)")
    public void dataScopePointcut() {
    }

    /**
     * 环绕通知：在方法执行前设置数据权限，执行后清除
     */
    @Around("dataScopePointcut() && @annotation(dataScope)")
    public Object around(ProceedingJoinPoint joinPoint, DataScope dataScope) throws Throwable {
        try {
            // 检查是否已登录
            if (!SessionHelper.isLogin()) {
                // 未登录时不设置数据权限
                return joinPoint.proceed();
            }

            // 获取当前用户ID
            Long userId = SessionHelper.getUserId();

            // 构建数据权限SQL片段
            String deptAlias = StringUtils.isNotBlank(dataScope.deptAlias()) ? dataScope.deptAlias() : "";
            String userAlias = StringUtils.isNotBlank(dataScope.userAlias()) ? dataScope.userAlias() : "";

            String sqlSegment = dataScopeService.buildDataScopeSQL(userId, deptAlias, userAlias);

            // 设置数据权限上下文
            DataScopeContext.DataScopeInfo scopeInfo = new DataScopeContext.DataScopeInfo()
                    .setUserId(userId)
                    .setDeptAlias(deptAlias)
                    .setUserAlias(userAlias)
                    .setEnabled(true)
                    .setSqlSegment(sqlSegment);

            DataScopeContext.set(scopeInfo);

            log.debug("设置数据权限: userId={}, sqlSegment={}", userId, sqlSegment);

            // 执行目标方法
            return joinPoint.proceed();
        } finally {
            // 清除数据权限上下文
            DataScopeContext.clear();
        }
    }
}

